#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>

int main() {
    SQLHENV env;
    SQLHDBC dbc;
    SQLHSTMT stmt;
    SQLRETURN ret;

    // 分配环境句柄
    ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
    if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
        fprintf(stderr, "无法分配 ODBC 环境\n");
        return 1;
    }

    // 设置 ODBC 版本
    SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);

    // 分配连接句柄
    ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
    if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
        fprintf(stderr, "无法分配连接句柄\n");
        SQLFreeHandle(SQL_HANDLE_ENV, env);
        return 1;
    }

    // DSN-less 连接字符串
    const char connStr[] =
        "DRIVER={FreeTDS};"
        "SERVER=your_db_address;PORT=1433;"
        "DATABASE=your_db_name;"
        "UID=your_db_user;"
        "PWD=your_db_pwd;"
        "TDS_VERSION=7.3;"
        "ClientCharset=UTF-8;"
        "Encrypt=yes;TrustServerCertificate=yes;";

    printf("正在连接 SQL Server...\n");
    ret = SQLDriverConnect(dbc, NULL, (SQLCHAR*)connStr, SQL_NTS,
                           NULL, 0, NULL, SQL_DRIVER_COMPLETE);

    if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
        fprintf(stderr, "连接失败！\n");

        SQLCHAR sqlState[6], message[256];
        SQLINTEGER nativeError;
        SQLSMALLINT msgLen;
        SQLSMALLINT i = 1;
        while (SQLGetDiagRec(SQL_HANDLE_DBC, dbc, i, sqlState, &nativeError, message, sizeof(message), &msgLen) == SQL_SUCCESS) {
            fprintf(stderr, "[DBC][%s] %ld %s\n", sqlState, (long)nativeError, message);
            i++;
        }

        SQLFreeHandle(SQL_HANDLE_DBC, dbc);
        SQLFreeHandle(SQL_HANDLE_ENV, env);
        return 1;
    }

    printf("✅ 成功连接到 SQL Server！\n");

    // 分配语句句柄
    ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
    if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
        ret = SQLExecDirect(stmt, (SQLCHAR*)"SELECT TOP 3 name FROM sys.tables", SQL_NTS);
        if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
            SQLCHAR table_name[128];
            while (SQLFetch(stmt) == SQL_SUCCESS) {
                SQLGetData(stmt, 1, SQL_CHAR, table_name, sizeof(table_name), NULL);
                printf("表名: %s\n", table_name);
            }
        } else {
            fprintf(stderr, "执行查询失败！\n");
            SQLCHAR sqlState[6], message[256];
            SQLINTEGER nativeError;
            SQLSMALLINT msgLen;
            SQLSMALLINT i = 1;
            while (SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i, sqlState, &nativeError, message, sizeof(message), &msgLen) == SQL_SUCCESS) {
                fprintf(stderr, "[STMT][%s] %ld %s\n", sqlState, (long)nativeError, message);
                i++;
            }
        }
        SQLFreeHandle(SQL_HANDLE_STMT, stmt);
    }

    // 断开连接
    SQLDisconnect(dbc);
    SQLFreeHandle(SQL_HANDLE_DBC, dbc);
    SQLFreeHandle(SQL_HANDLE_ENV, env);

    return 0;
}
